package common.liusany.admin.service.account;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import common.liusany.admin.bean.Setting;
import common.liusany.admin.entity.account.Email;
import common.liusany.admin.utils.SettingUtil;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * MIME邮件服务类.
 * 
 * 演示由Freemarker引擎生成的的html格式邮件, 并带有附件.
 
 * @author calvin
 */
public class MimeMailService {

	private static final String DEFAULT_ENCODING = "utf-8";

	private static Logger logger = LoggerFactory.getLogger("MimeMailService");
	
	/**
	 * 保存发送成功的邮件id
	 */
	public static List<Long> IDLIST = Collections.synchronizedList(new LinkedList<Long>() );
	/**
	 * 保存发送失败的邮件id
	 */
	public static List<Long> FIDLIST = Collections.synchronizedList(new LinkedList<Long>() );
	
	private JavaMailSender mailSender;

	private Template template;
	
	
	@javax.annotation.Resource
	private ThreadPoolTaskExecutor taskExecutor;
	
	/**
	 * 发送邮件测试
	 * @param smtpFromMail
	 * @param smtpHost
	 * @param smtpPort
	 * @param smtpUsername
	 * @param smtpPassword
	 * @param toMail
	 */
	public void sendSmtpTestMail(String smtpFromMail, String smtpHost, Integer smtpPort,
			String smtpUsername, String smtpPassword, String toMail,String subject) {
		try {
			JavaMailSenderImpl javaMailSenderImpl = (JavaMailSenderImpl)mailSender;
			javaMailSenderImpl.setHost(smtpHost);
			javaMailSenderImpl.setPort(smtpPort);
			javaMailSenderImpl.setUsername(smtpUsername);
			javaMailSenderImpl.setPassword(smtpPassword);
			
			MimeMessage mimeMessage = javaMailSenderImpl.createMimeMessage();
			MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, DEFAULT_ENCODING);
			helper.setTo(toMail);
			helper.setFrom(MimeUtility.encodeWord("<"+smtpFromMail+">"));
			helper.setSubject(subject);
			String content = generateContent("admin");
			helper.setText(content, true);
			Long beginTime = System.currentTimeMillis();
			mailSender.send(mimeMessage);
			Long endTime = System.currentTimeMillis();
			logger.info("发送邮件共耗时:"+(endTime - beginTime) / 1000	+ "秒");
		} catch (IOException e) {
			logger.error(e.getMessage());
		} catch (MessagingException e) {
			logger.error(e.getMessage());
		}
	}
	
	
	// 增加邮件发送任务
	public void addSendMailTask(final MimeMessage mimeMessage, final Email email) {
		try {
			taskExecutor.execute(new Runnable() {
				public void run(){
					//正式发送邮件
					    StringBuilder logInfo = new StringBuilder();;
						try {
								mailSender.send(mimeMessage);
								IDLIST.add(email.getId());
								logger.info(logInfo.append("Email send success | Email-ID: ").append(email.getId())
										.append(" | Email-address：").append(email.getEmail()).toString());
							
						} catch (MailException e) {
							FIDLIST.add(email.getId());
							logger.error(logInfo.append("Email send failed | Email-ID:").append(email.getId())
									.append(" | Email-address：").append(email.getEmail()).append(" |Mail server connection failed").toString());
						} finally{
							logInfo = null;
						}
				}
			});
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}
	
	@Transactional
	public void sendTest(final MimeMessage mimeMessage,final Email email){
		try {
			
			Thread.sleep(800);//假设发送邮件需要4秒钟
			logger.info("邮件已发送,emial id--"+email.getId()+"  email address:  "+email.getEmail());
			IDLIST.add(email.getId());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
	/**
	 * 发送MIME格式的用户修改通知邮件.
	 */
	public void sendHtmlMail(Email mail) {

		try {
			Setting setting = SettingUtil.getSetting();
			JavaMailSenderImpl javaMailSenderImpl = (JavaMailSenderImpl)mailSender;
			javaMailSenderImpl.setHost(setting.getSmtpHost());
			javaMailSenderImpl.setPort(setting.getSmtpPort());
			javaMailSenderImpl.setUsername(setting.getSmtpUsername());
			javaMailSenderImpl.setPassword(setting.getSmtpPassword());
			
			MimeMessage msg = mailSender.createMimeMessage();
			MimeMessageHelper helper = new MimeMessageHelper(msg, true, DEFAULT_ENCODING);
			helper.setTo(mail.getEmail());
			helper.setFrom(setting.getSmtpFromMail());
			helper.setSubject(setting.getSubject());

			String content = generateContent("admin");
			helper.setText(content, true);

//			File attachment = generateAttachment();
//			helper.addAttachment("mailAttachment.txt", attachment);

			addSendMailTask(msg,mail);
			
		} catch (MessagingException e) {
			logger.error("构造邮件失败", e.getMessage());
		} catch (Exception e) {
			logger.error("邮件初始化错误", e.getMessage());
		}
	}
	
	
	/**
	 * 发送MIME格式的用户修改通知邮件.
	 */
	public void sendNotificationMail(String toMail,String userName) {

		try {
			MimeMessage msg = mailSender.createMimeMessage();
			MimeMessageHelper helper = new MimeMessageHelper(msg, true, DEFAULT_ENCODING);
			helper.setTo(toMail);
			helper.setFrom("springside3.demo@gmail.com");
			helper.setSubject("【湖南卫视“李湘”私人减肥秘笈“超级P57”】100%正品 权威认证防伪标致 超级P57来了！团购价88元！抢购源自南非食用蝴蝶亚仙人掌（Hoodia）的天然有效成分");

			String content = generateContent(userName);
			helper.setText(content, true);

		} catch (MessagingException e) {
			logger.error("构造邮件失败", e);
		} catch (Exception e) {
			logger.error("发送邮件失败", e);
		}
	}

	/**
	 * 使用Freemarker生成html格式内容.
	 */
	private String generateContent(String userName) throws MessagingException {

		try {
//			Map context = Collections.singletonMap("userName", userName);
			return FreeMarkerTemplateUtils.processTemplateIntoString(template, null);
		} catch (IOException e) {
			logger.error("生成邮件内容失败, FreeMarker模板不存在", e);
			throw new MessagingException("FreeMarker模板不存在", e);
		} catch (TemplateException e) {
			logger.error("生成邮件内容失败, FreeMarker处理失败", e);
			throw new MessagingException("FreeMarker处理失败", e);
		}
	}
	
	
	
	

	/**
	 * 获取classpath中的附件.
	 */
	private File generateAttachment() throws MessagingException {
		try {
			Resource resource = new ClassPathResource("/email/mailAttachment.txt");
			return resource.getFile();
		} catch (IOException e) {
			logger.error("构造邮件失败,附件文件不存在", e);
			throw new MessagingException("附件文件不存在", e);
		}
	}

	/**
	 * Spring的MailSender.
	 */
	public void setMailSender(JavaMailSender mailSender) {
		this.mailSender = mailSender;
	}

	/**
	 * 注入Freemarker引擎配置,构造Freemarker 邮件内容模板.
	 */
	public void setFreemarkerConfiguration(Configuration freemarkerConfiguration) throws IOException {
		//根据freemarkerConfiguration的templateLoaderPath载入文件.
		template = freemarkerConfiguration.getTemplate("mailTemplate.ftl", DEFAULT_ENCODING);
	}
}
